home *** CD-ROM | disk | FTP | other *** search
- /* PLG file i/o */
- // NEW version by Dave Stampe
-
- /* Original PLG loader written by Bernie Roehl, March 1992 */
- // PLG prescanning for total vertex pointers added by Dave Stampe, 22/11/93
-
- // This is a COMPLETE REWRITE for VR-386, by Dave Stampe 8/1/94
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
-
-
-
- #include <stdio.h>
- #include <stdlib.h> /* atoi(), atol() */
- #include <string.h>
- #include <alloc.h>
- #include <ctype.h> /* isalnum() */
-
- #include "vr_api.h"
- #include "intmath.h"
-
- static int load_err = 0; /* set if an error was encountered during loading */
- static int err_line = 1; /* line on which error occurred */
-
- static char *plg_errmsgs[] = {
- "No error",
- "Bad syntax in header line",
- "Couldn't create new object",
- "Couldn't add representation",
- "Early EOF while reading vertices",
- "Bad syntax in vertex line",
- "Early EOF while reading polygons",
- "Missing vertex count in polygon line",
- "Missing vertex index in polygon line",
- "Couldn't add polygon",
- "Vertex number out of range",
- NULL };
-
- static char errm[50];
-
- char *plg_error(int *errnum)
- {
- if(errnum) *errnum = load_err;
- if(!load_err) return NULL;
- sprintf(errm, "File line %d: %s", plg_errmsgs[-load_err]);
- return errm;
- }
-
-
- static float xrescale = 1, yrescale = 1, zrescale = 1;
- static MATRIX obj_xform;
-
-
- void strip_comment(char *buff) /* also trim newline character(s) */
- {
- char *p;
-
- if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* trim newline */
- if ((p = strchr(buff, '#')) != NULL) *p = '\0'; /* trim comment */
- if ((p = strchr(buff, '*')) != NULL) *p = '\0'; /* future expansion */
- if(sscanf(buff,"%*s")==EOF) buff[0] = 0; /* dump tabs, etc */
- }
-
- static long default_size;
- static int maxpolys;
- static int maxverts;
- static int multirep = 0;
-
- static int prescan = 0; // PRESCAN to find total poly vertices
- static int tpverts = 0;
- static int tpvcount = 0;
-
-
- // if <obj> is null, creates new fixed object
- // else loads new representation to <obj>
- static int load_in_plg_file(FILE *in, OBJECT **obj)
- {
- char tbuff[1000], objname[100];
- int nv, np, i;
- char *p;
- int size = 0;
- int multi = (*obj) ? 1 : 0; /* multi-reps if not null object */
-
- tpvcount = 0;
- multirep = 0;
-
- /* skip blank lines */
- do {
- if (fgets(tbuff, sizeof(tbuff), in) == NULL) return -1;
- ++err_line;
- if (strstr(tbuff,"#MULTI")) multi++;
- if (multi) multirep++;
- strip_comment(tbuff);
- }
- while (tbuff[0] == '\0'); // NEW NOW LOADS TPVERTS
-
- if (sscanf(tbuff, "%s %d %d %d", objname, &nv, &np, &tpverts) < 3)
- {
- load_err = -1;
- return -1;
- }
-
- if(tpverts) // we got our count!
- {
- prescan = 0;
- }
-
- if (multi && (p = strchr(objname, '_')) != NULL)
- {
- *p++ = 0;
- size = atoi(p);
- }
- else size = default_size; /* default: use largest detail always */
-
- if(!prescan)
- {
- if (*obj == NULL)
- {
- if ((*obj = create_fixed_object(nv, np, tpverts)) == NULL)
- {
- load_err = -2;
- return -1;
- }
- set_representation_size(*obj, size);
- }
- else
- {
- if (add_representation(*obj, size, nv, np, tpverts) == NULL)
- {
- load_err = -3;
- return -1;
- }
- }
- }
-
- maxpolys = np;
- maxverts = nv;
-
- for (i = 0; i < nv; ++i) /* load in vertices */
- {
- float x, y, z;
- /* skip blank lines */
- do
- {
- if (fgets(tbuff, sizeof(tbuff), in) == NULL)
- {
- load_err = -4;
- return -1;
- }
- ++err_line;
- strip_comment(tbuff);
- }
- while (tbuff[0] == '\0');
-
- if (sscanf(tbuff, "%f %f %f", &x, &y, &z) != 3)
- {
- load_err = -5;
- return -1;
- }
-
- if(!prescan) // map the vertex
- {
- COORD xx = x*xrescale;
- COORD yy = y*yrescale;
- COORD zz = z*zrescale;
-
- matrix_point(obj_xform, &xx, &yy, &zz);
- add_vertex(*obj, xx, yy, zz);
- }
- }
-
- for (i = 0; i < np; ++i) /* load polygons */
- {
- int j, npoints;
- unsigned color;
- POLY *poly;
- char *p;
- /* skip blank lines */
- do
- {
- if (fgets(tbuff, sizeof(tbuff), in) == NULL)
- {
- load_err = -6;
- return -1;
- }
- ++err_line;
- strip_comment(tbuff);
- }
- while (tbuff[0] == '\0');
-
- color = convert_color(tbuff,&p);
- if ((p = strtok(p, " \t")) == NULL)
- {
- load_err = -7;
- return -1;
- }
- npoints = atoi(p);
- if (prescan)
- {
- tpvcount += npoints; // this is all prescan wanted!
- }
- else
- {
- if ((poly = add_poly(*obj, color, npoints)) == NULL)
- {
- load_err = -9;
- return -1;
- }
- for (j = 0; j < npoints; ++j)
- {
- int vertnum;
- if ((p = strtok(NULL, " \t")) == NULL)
- {
- load_err = -8;
- return -1;
- }
- vertnum = atoi(p);
- if (vertnum < 0 || vertnum >= maxverts)
- {
- load_err = -10;
- return -1;
- }
- add_point(*obj, poly, vertnum);
- }
- compute_object(*obj); /* will do current rep only */
- }
- }
- load_err = 0;
- return 0;
- }
-
-
- // read file with prescan if it doesn't have total poly verts
- // if <obj> is null, creates new fixed object
- // else loads new representation to <obj>
- static int read_plg_file(FILE *in, VISOBJ **obj)
- {
- int retc;
- long fptr = ftell(in);
- prescan = 1;
- tpverts = 0;
- if (0!=(retc=load_in_plg_file(in, obj))) return retc;
-
- if(!prescan) return retc; // we got total poly verts thru file!
-
- fseek(in, fptr, 0);
- prescan = 0;
- tpverts = tpvcount;
- return load_in_plg_file(in, obj);
- }
-
- // create the matrix and scales for object loading
- void create_obj_xform(POSE *p, float xs, float ys, float zs)
- {
- if (p->x == DONTCARE) p->x = 0;
- if (p->y == DONTCARE) p->y = 0;
- if (p->z == DONTCARE) p->z = 0;
- if (p->rx == DONTCARE) p->rx = 0;
- if (p->ry == DONTCARE) p->ry = 0;
- if (p->rz == DONTCARE) p->rz = 0;
- multi_matrix(obj_xform, p->rx, p->ry, p->rz, p->x, p->y, p->z, RYXZ);
- if (xs<=0.001) xrescale = 0.001; else xrescale = xs;
- if (ys<=0.001) yrescale = 0.001; else yrescale = ys;
- if (zs<=0.001) zrescale = 0.001; else zrescale = zs;
- }
-
- // loads a new rep to an old object.
- // useful to create morphing animations
- // just loads FIRST if not multi-rep file
- OBJECT *load_extra_plg_representation(FILE *in, OBJECT *obj, POSE *p,
- float sx, float sy, float sz, WORD size)
- {
- int ocount = 0;
- default_size = size;
- load_err = 0;
- err_line = 1;
- create_obj_xform(p, sx, sy, sz);
-
- while (read_plg_file(in, &obj) == 0) // read all we can
- {
- ocount++;
- if (!multirep) break;
- }
- default_size = 0;
- if (ocount == 0) return NULL;
- return obj;
- }
-
- // loads single and multi-rep files
- // will load only one object: call again if not EOF
- OBJECT *load_plg_object(FILE *in, POSE *p,
- float sx, float sy, float sz, WORD depth)
- {
- OBJECT *obj = NULL;
- int ocount = 0;
-
- default_size = 0;
- load_err = 0;
- err_line = 1;
- create_obj_xform(p, sx, sy, sz);
-
- while (read_plg_file(in, &obj) == 0)
- {
- ocount++;
- if (!multirep) break;
- }
- if (ocount == 0) return NULL;
- set_object_sorting(obj, depth);
- mark_object_invisible(obj); // invisible till placed in world
- return obj;
- }
-
-
- WORD load_plg_to_objlist(FILE *in, OBJLIST *objlist, WORD maxobj, POSE *p,
- float sx, float sy, float sz, WORD depth)
- {
- VISOBJ *obj;
- int olcount = 0;
- int ocount;
-
- default_size = 0;
- load_err = 0;
- err_line = 1;
- create_obj_xform(p, sx, sy, sz);
-
- while(!feof(in) && olcount<maxobj)
- {
- ocount = 0;
- obj = NULL;
- while (read_plg_file(in, &obj) == 0)
- {
- ocount++;
- if (!multirep) break;
- }
- if (ocount == 0) goto load_failed;
- set_object_sorting(obj, depth);
- mark_object_invisible(obj); // invisible to keep on list till placed in world
- add_to_objlist(objlist, obj);
- olcount++;
- }
- load_failed:
- return olcount;
- }
-
-
-
-
- // save a PLG object
- // no name
- BOOL save_plg(OBJECT *obj, FILE *out, BOOL world)
- {
- int nv, np, tv, i; /* now saves all representations */
- char buff[100];
- int multi = 0;
-
- if(!(obj=object2visobj(obj))) return -1; // is a segment!
-
- select_first_representation(obj); // test if multiple representations
- multi = select_next_representation(obj);
- select_first_representation(obj); // back to first
-
- if(multi) fprintf(out, "##MULTI\n");
-
- do
- {
- get_obj_info(obj, &nv, &np);
- tv = total_object_pverts(obj); // now saves total vtx count for future upgrades
- fprintf(out, "SAVED %d %d *d\n", nv, np, tv);
- for (i = 0; i < nv; ++i)
- {
- long x, y, z;
-
- if (world) get_vertex_world_info(obj, i, &x, &y, &z);
- else get_vertex_info(obj, i, &x, &y, &z);
- fprintf(out, "%ld %ld %ld\n", x, y, z);
- }
- for (i = 0; i < np; ++i)
- {
- int j, n, verts[1000];
- unsigned c;
-
- get_poly_info(obj, i, &c, &n);
- fprintf(out, "0x%04.4X %d", c & 0x7FFF, n);
- for (j = 0; j < n; ++j)
- {
- fprintf(out, " %d", get_poly_vertex_index(obj, i, j));
- }
- fprintf(out, "\n");
- }
- }
- while (!select_next_representation(obj));
-
- return 0;
- }
-